package config

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"log"
	mrand "math/rand"
	"os"

	"golang.org/x/crypto/bcrypt"

	"homepage-backend/internal/models"
)

type Config struct {
	BaseURL               string          `json:"baseURL"`
	SitesFilePath         string          `json:"sitesFilePath"`
	AnnouncementsFilePath string          `json:"announcementsFilePath"`
	LinksFilePath         string          `json:"linksFilePath"`
	AllowedOrigins        []string        `json:"allowedOrigins"`
	PageData              models.PageData `json:"pagedata"`
	AdminUser             string          `json:"adminUser"`
	AdminPassHash         string          `json:"adminPassHash"`
	JWTSecret             string          `json:"jwtSecret"`
}

var GlobalConfig Config

// randomString 生成指定长度的随机字符串
func randomString(n int) string {
	b := make([]byte, n)
	_, err := rand.Read(b)
	if err != nil {
		for i := range b {
			b[i] = byte(65 + mrand.Intn(26))
		}
	}
	return base64.RawURLEncoding.EncodeToString(b)[:n]
}

// RandomString 生成指定长度的随机字符串（导出）
func RandomString(n int) string {
	return randomString(n)
}

// hashPassword 对密码进行sha256+bcrypt二次加密
func HashPassword(password string) (string, error) {
	sha := sha256.Sum256([]byte(password))
	hash, err := bcrypt.GenerateFromPassword(sha[:], bcrypt.DefaultCost)
	return string(hash), err
}

// verifyPassword 校验密码
func VerifyPassword(hash, password string) bool {
	sha := sha256.Sum256([]byte(password))
	return bcrypt.CompareHashAndPassword([]byte(hash), sha[:]) == nil
}

// LoadConfig 从配置文件加载配置，并自动生成缺失的敏感字段
func LoadConfig(configPath string) error {
	file, err := os.Open(configPath)
	if err != nil {
		log.Println("Error opening config file: ", err)
		return err
	}
	defer file.Close()

	decoder := json.NewDecoder(file)
	if err := decoder.Decode(&GlobalConfig); err != nil {
		log.Println("Error decoding config file: ", err)
		return err
	}

	changed := false
	if GlobalConfig.AdminUser == "" {
		GlobalConfig.AdminUser = "admin"
		changed = true
	}
	if GlobalConfig.AdminPassHash == "" {
		pass := randomString(12)
		hash, _ := HashPassword(pass)
		GlobalConfig.AdminPassHash = string(hash)
		log.Printf("[安全提示] 首次生成的管理员密码: %s\n", pass)
		changed = true
	}
	if GlobalConfig.JWTSecret == "" {
		GlobalConfig.JWTSecret = randomString(32)
		changed = true
	}
	if changed {
		f, err := os.Create(configPath)
		if err == nil {
			enc := json.NewEncoder(f)
			enc.SetIndent("", "    ")
			enc.Encode(GlobalConfig)
			f.Close()
		}
	}
	return nil
}
